/**
This file is part of Gel2DE.

    Gel2DE is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Gel2DE is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with Gel2DE.  If not, see <http://www.gnu.org/licenses/>.

	Copyright (C) 2012, University of Bergen
*/

#pragma once

#include <itkImage.h>
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionIterator.h"
#include "itkRGBPixel.h"
#include "itkScalableAffineTransform.h"
#include "itkScaleTransform.h"
#include "itkResampleImageFilter.h"
#include "itkNearestNeighborInterpolateImageFunction.h"
#include "itkLinearInterpolateImageFunction.h"
#include "itkShiftScaleImageFilter.h"
#include "itkRecursiveGaussianImageFilter.h"
#include "itkMatrix.h"
#include "itkPoint.h"
#include "itkImageIOBase.h"
#include "itkMetaImageIO.h"
#include <string.h>
#include <set>
#include "tinyxml.h"
#include "itkFlipImageFilter.h"
#include "GelImageTransformation.h"
#include "vtkFileOutputWindow.h"

class GelImage
{
public:
	GelImage(TiXmlElement* aGelImageElement, GelImageTransformation* aGelImageTransformation, vtkFileOutputWindow *aLogFile);
	~GelImage(void);

	typedef unsigned short PixelType;
	typedef float ScaledPixelType;
	//char for 8-bit
	//use typename for templates
	typedef itk::Image<PixelType, 2> ImageType;
	typedef itk::Image<ScaledPixelType, 2> ScaledImageType;
	typedef itk::ImageFileReader<ImageType> Reader;
	typedef itk::ImageFileWriter<ImageType> Writer;
	typedef itk::ImageRegionConstIterator<ImageType> ConstIteratorType;
	typedef itk::ScaleTransform<double, 2> ScaleTransformType;
	typedef itk::ResampleImageFilter<ImageType, ImageType> ResampleImageType;
	typedef itk::LinearInterpolateImageFunction<ImageType, double> InterpolatorType;
	typedef itk::ShiftScaleImageFilter<ImageType, ImageType> ShiftScaleImageFilter;
	typedef itk::RecursiveGaussianImageFilter<ImageType, ImageType> RecursiveGaussianImageFilter;
	
	double GetParameterValue(std::string);
	BOOL HasParameterValue(std::string);
	PixelType GetCurrentPixelRaw();
	double GetSumIntensity();
	double GetAvgIntensity();
	double GetRMSIntensity();
	double GetMedian();
	void SetReleaseDataFlags(bool aReleaseData);

	void SetRoi(ImageType::RegionType aRegion);
	bool IsAtEnd();
	void MoveToNextPixel();
	void MoveToStart();
	ImageType::Pointer GetImage();
	const char* GetFileName();

	void Rotate(double);
	void Translate(double[]);
	void SetCenterOfRotation(double[]);
	void Scale(double);
	void UseStd();
	void UseData();

	void SetEnabled(bool);
	void SetFixed(bool);

	bool isEnabled();
	bool isFixed();
	void Update();
	void SetupIterator();

	int GetNormalizationMode();


	TiXmlElement* ToXML();
	void FromXML(TiXmlElement*);

	std::set<const std::string> GetParameterTypes();
	void SetBlurLevel(double aSigma);
	double GetBlurLevel();
	void SetNormalizationMode(int aNormalizationMode, double aGlobalScale);

	static const int NO_NORM = 0;
	static const int MEAN_NORM = 1;
	static const int MEDIAN_NORM = 2;
	static const int ZSCORE_NORM = 3;

private:

	void CalculateIntensityStatistics();

	void SetupDataReader(const char*);
	void SetupStdReader(const char*);
	void SetupResampler();

	Reader::Pointer m_datReader;
	Reader::Pointer m_stdReader;

	GelImageTransformation::TransformType::Pointer m_transform;
	ResampleImageType::Pointer m_resampler;

	ShiftScaleImageFilter::Pointer m_shiftScaleFilter;
	RecursiveGaussianImageFilter::Pointer m_gaussianFilterX;
	RecursiveGaussianImageFilter::Pointer m_gaussianFilterY;

	ConstIteratorType* m_iterator;
	std::map<const std::string, double>* m_parameterMap;
	//double m_t;
	double m_RMSIntensity;
	double m_AvgIntensity;
	double m_SumIntensity;
	PixelType m_Median;

	double m_angle;
	double m_scale[2];

	//todo: belongs to gelstack class!
	bool m_fixed;
	bool m_enabled;

	int m_normalizationMode;

	vtkFileOutputWindow *m_logFile;

};
